package com.kevin.session.defaults;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import org.apache.commons.lang3.StringUtils;

import com.kevin.action.BuildSql;
import com.kevin.action.JdbcParams;
import com.kevin.action.builder.BaseSqlBuildHandler;
import com.kevin.exceptions.ExceptionFactory;
import com.kevin.executors.Executor;
import com.kevin.session.Configuration;
import com.kevin.session.SqlSession;
import com.kevin.table.MDataTable;

public class DefaultSqlSession implements SqlSession {
	private final Executor executor;
	private final boolean autoCommit;
	private String tableName;
	private BaseSqlBuildHandler sqlBuildHandler;
	
	public DefaultSqlSession(String tableName,Configuration configuration, Executor executor, boolean autoCommit) {
		this.executor = executor;
		this.autoCommit = autoCommit;
		this.tableName = tableName;
		sqlBuildHandler = configuration.newSqlBuildHandler(tableName, executor);
	}

	public DefaultSqlSession(String tableName,Configuration configuration, Executor executor) {
		this(tableName,configuration, executor, false);
	}

	public DefaultSqlSession(Configuration configuration, Executor executor) {
		this(null,configuration, executor, false);
	}
	@Override
	public void close() {
		try {
			executor.close(!autoCommit);
		} finally {

		}
	}
	
	@Override
	public MDataTable select(Integer pageIndex, Integer pageSize) {
		return select(pageIndex, pageSize, null, null, new String[0]);
	}

	@Override
	public MDataTable select(Integer pageIndex, Integer pageSize, String where) {
		return select(pageIndex, pageSize, where, null, new String[0]);
	}

	@Override
	public MDataTable select(Integer pageIndex, Integer pageSize, String where, JdbcParams[] paramList) {
		return select(pageIndex, pageSize, where, paramList, new String[0]);
	}

	@Override
	public MDataTable select(Integer pageIndex, Integer pageSize, String... columns) {
		return select(pageIndex, pageSize, null, null, columns);
	}

	@Override
	public MDataTable select(Integer pageIndex, Integer pageSize, String where, String... columns) {
		return select(pageIndex, pageSize, where, null, columns);
	}

	@Override
	public MDataTable select(Integer pageIndex, Integer pageSize, String where,
			JdbcParams[] paramList, String... columns) {
		Integer rowCount = 0;
		tableName = formatForView(tableName);
		MDataTable table = new MDataTable(tableName.contains("(") ? "SysDefaultCustomTable" : tableName);
		table.loadRowStruct(sqlBuildHandler.getStruct());
		boolean bypager = pageIndex > 0 && pageSize > 0;
		if (bypager) {
			rowCount = count(where, paramList);
		}

		String sql = sqlBuildHandler.selectSql(columns, pageIndex, pageSize, rowCount, where);
		ResultSet sdResult = executor.query(sql, paramList);
		table.loadData(sdResult);
		table.setTotal(rowCount);
		return table;
	}

	@Override
	public MDataTable newDataTable(){
		MDataTable table = new MDataTable(tableName);
		table.loadRowStruct(sqlBuildHandler.getStruct());
		return table;
	}
	
	
	@Override
	public int count(String where) {	
		return count(where,new JdbcParams[0]);
	}
		
	@Override
	public int count(String where, JdbcParams... paramList) {
		tableName = formatForView(tableName);
		int count = 0;
		try {
			String sql = sqlBuildHandler.countSql(where);
			ResultSet result = executor.query(sql, paramList);
			if (result.next()) {
				count = result.getInt(1);
			}
		} catch (SQLException e) {
			throw ExceptionFactory.Exception(e);
		}
		return count;
	}

	@Override
	public int insert(MDataTable table) {
		ArrayList<BuildSql> sqlList = sqlBuildHandler.insertSql(table);
		int count = 0;
		for (BuildSql buildSql : sqlList) {
			int affact = executor.update(buildSql.getSql(), buildSql.getJdbcParams());
			if(affact > 0) count += affact;
		}
		return count;
	}
	
	@Override
	public int update(MDataTable table){
		return update(table, null);
	}
	
	@Override
	public int update(MDataTable table,String where){
		ArrayList<BuildSql> sqlList = sqlBuildHandler.updateSql(table, where);
		
		int count = 0;
		for (BuildSql buildSql : sqlList) {
			int affact = executor.update(buildSql.getSql(), buildSql.getJdbcParams());
			if(affact > 0) count += affact;
		}
		return count;
	}
	
	
	@Override
	public boolean delete(String where){
		String sql = sqlBuildHandler.deleteSql(where);
		return executor.update(sql, null) > 0;
	}
	
	private String formatForView(String tableName) {
		tableName = tableName.trim();
		if (StringUtils.startsWithIgnoreCase(tableName, "select ")
				|| (tableName.contains(" ") && tableName.charAt(0) != '(')) {
			tableName = "(" + tableName + ") v";
		}
		return tableName;
	}
}
